using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.Odbc;
using System.Data.Common;
using System.Globalization;

public partial class _Default : System.Web.UI.Page 
{
    //TODO: add "Seclect your lang", universal strings included in all resources

    private Database db;
    /// <summary>
    /// Shows a form for generating resources or an XML spreadsheet
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void Page_Load(object sender, EventArgs e)
    {
        db = new Database();
        db.OpenConnection();
        using(Database.Command cmd = db.CreateCommand()) {
            cmd.CommandText = "SELECT id, displayname FROM applications ORDER BY displayname ASC";
            Database.DataAdapter adapter = new Database.DataAdapter(cmd);
            DataSet ds = new DataSet();
            adapter.Fill(ds);
            if(!Page.IsPostBack) {
                radApplication.DataSource = ds;
                radApplication.DataValueField = "id";
                radApplication.DataTextField = "displayname";
                radApplication.DataBind();

                List<KeyValuePair<string, string>> templates = EnumBinder.EnumHelper.ToList(typeof(Constants.ResourceType));// new List<KeyValuePair<string, string>>();
                cmd.CommandText = "SELECT id, name FROM templates";
                DbDataReader reader = cmd.ExecuteReader();
                while(reader.Read()) {
                    templates.Add(new KeyValuePair<string, string>(reader["id"].ToString(), reader["name"].ToString()));
                }
                radFormat.DataSource = templates;
                radFormat.DataTextField = "Value";
                radFormat.DataValueField = "Key";
                radFormat.DataBind();
                if(radApplication.Items.Count > 0) {
                    radApplication.SelectedIndex = 0;
                    ShowLanguages(null, EventArgs.Empty);
                    mltNoApplications.ActiveViewIndex = 1;
                }
                txtThreshold.Text = Constants.DefaultThreshold.ToString();
            }
        }
        lblBundleError.Visible = false;
        db.CloseConnection();
    }

    /// <summary>
    /// Processes the request and generates the output
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void btnGenerate_Click(object sender, EventArgs e) {
        Page.Validate();
        if(!Page.IsValid) {
            return;
        }
        string applicationId = radApplication.SelectedValue;
        int threshold = int.Parse(txtThreshold.Text);
        bool includeSummary = chkIncludeSummary.Checked;
        List<string> tmpBundles = new List<string>(),
                     tmpLanguages = new List<string>();
        foreach(ListItem itm in lstBundles.Items) {
            if(itm.Selected) {
                tmpBundles.Add(itm.Value);
            }
        }
        foreach(ListItem itm in lstLanguages.Items) {
            if(itm.Selected) {
                tmpLanguages.Add(itm.Value);
            }
        }
        string applicationName = string.Empty,
               defaultLanguage = string.Empty;
        string[] bundles = tmpBundles.ToArray(),
                 languages = tmpLanguages.ToArray();
        db = new Database();
        db.OpenConnection();
        using(Database.Command cmd = db.CreateCommand()) {
            cmd.CommandText = "SELECT name, defaultlanguage FROM applications WHERE id = @p";
            cmd.AddParameterWithValue("@p", applicationId);
            DbDataReader reader = cmd.ExecuteReader();
            if(!reader.Read()) {
                throw new ArgumentException("Application not found:" + applicationId);
            }
            try {
                applicationName = reader["name"].ToString();
                defaultLanguage = reader["defaultLanguage"].ToString();
            } catch {
                db.CloseConnection();
                throw new ArgumentException("Could not load application data");
            }
            reader.Close();
        }
        if(radFormat.SelectedIndex < Enum.GetValues(typeof(Constants.ResourceType)).Length) {
            Constants.ResourceType type = (Constants.ResourceType)Enum.Parse(typeof(Constants.ResourceType), radFormat.SelectedValue);
            switch(type) {
                case Constants.ResourceType.Firefox:
                    using(Database.Command cmd = db.CreateCommand()) {
                        cmd.CommandText = "SELECT name FROM bundles WHERE application = @p";
                        cmd.AddParameterWithValue("@p", applicationId);
                        DbDataReader reader = cmd.ExecuteReader();
                        bool hasXUL = false,
                             hasJS = false;
                        while(reader.Read()) {
                            switch(reader.GetString(0).ToLower()) {
                                case "xul":
                                    hasXUL = true;
                                    break;
                                case "javascript":
                                    hasJS = true;
                                    break;
                            }
                        }
                        if(hasXUL && hasJS) {
                            ResourceGenerator.GenerateFirefox(applicationName, applicationId, threshold, bundles, languages, defaultLanguage, includeSummary);
                        } else {
                            lblBundleError.Text = "Bundles named <em>JavaScript</em> and XUL must be present to output to this format. The selected application lacks one or both of these bundles.";
                            lblBundleError.Visible = true;
                        }
                        reader.Close();
                    }
                    break;
                case Constants.ResourceType.Java:
                    ResourceGenerator.GenerateJava(applicationName, applicationId, threshold, bundles, languages, defaultLanguage, includeSummary);
                    break;
                case Constants.ResourceType.DotNet:
                    ResourceGenerator.GenerateDotNet(applicationName, applicationId, threshold, bundles, languages, defaultLanguage, includeSummary, false);
                    break;
                case Constants.ResourceType.DotNetCF:
                    ResourceGenerator.GenerateDotNet(applicationName, applicationId, threshold, bundles, languages, defaultLanguage, includeSummary, true);
                    break;
            }
        } else { // not a preset, must be a custom format
            using(Database.Command cmd = db.CreateCommand()) {
                cmd.CommandText = "SELECT filename, filestart, line, fileend FROM templates WHERE id = @templateId";
                cmd.AddParameterWithValue("@templateId", radFormat.SelectedValue);
                DbDataReader reader = cmd.ExecuteReader();
                if(!reader.Read()) {
                    throw new ArgumentException("Template not found:" + applicationId);
                }
                string templateFileName,
                       templateFileStart,
                       templateFileEnd,
                       templateElement;
                try {
                    templateFileName = reader["filename"].ToString();
                    templateFileStart = reader["filestart"].ToString();
                    templateFileEnd = reader["fileend"].ToString();
                    templateElement = reader["line"].ToString();
                } catch {
                    db.CloseConnection();
                    throw new ArgumentException("Could not load template data");
                }
                reader.Close();
                KeyValuePair<string, Dictionary<string, Dictionary<string, Dictionary<string, string>>>> rawResources = ResourceGenerator.GenerateBundles(applicationName, applicationId, threshold, bundles, languages, defaultLanguage, includeSummary);
                ResourceGenerator.GenerateCustom(applicationName, rawResources, templateFileName, templateFileStart, templateFileEnd, templateElement);
            }
        }
        db.CloseConnection();
    }

    /// <summary>
    /// Shows the languages and bundles for the application selected.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ShowLanguages(object sender, EventArgs e) {
        if(radApplication.SelectedValue == null) {
            return;
        }
        db = new Database();
        db.OpenConnection();
        using(Database.Command cmd = db.CreateCommand()) {
            cmd.CommandText = "SELECT languages FROM applications WHERE id = @p";
            cmd.AddParameterWithValue("@p", radApplication.SelectedValue);
            ListComparer cmp = new ListComparer();
            List<ListItem> tempLanguages = new List<ListItem>(),
                           tempBundles = new List<ListItem>();
            lstLanguages.Items.Clear();
            string rawLanguages = cmd.ExecuteScalar().ToString();
            foreach(string abbrev in rawLanguages.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) {
                ListItem itm = null;
                try {
                    itm = new ListItem(CultureInfo.GetCultureInfo(abbrev).EnglishName, abbrev);
                } catch {
                    itm = new ListItem(abbrev);
                }
                itm.Selected = true;
                tempLanguages.Add(itm);
            }
            tempLanguages.Sort(cmp);
            lstLanguages.Items.AddRange(tempLanguages.ToArray());
            if(lstLanguages.Items.Count == 0) {
                ListItem itm = new ListItem("No languages found", "");
                itm.Selected = true;
                lstLanguages.Items.Add(itm);
                lstLanguages.Enabled = false;
            } else {
                lstLanguages.Enabled = true;
            }

            lstBundles.Items.Clear();
            cmd.CommandText = "SELECT id, name FROM bundles WHERE application = @p";
            DbDataReader reader = cmd.ExecuteReader();
            while(reader.Read()) {
                ListItem itm = new ListItem(reader["name"].ToString(), reader["id"].ToString());
                itm.Selected = true;
                tempBundles.Add(itm);
            }
            tempBundles.Sort(cmp);
            lstBundles.Items.AddRange(tempBundles.ToArray());
            if(lstBundles.Items.Count == 0) {
                ListItem itm = new ListItem("No bundles found", "");
                itm.Selected = true;
                lstBundles.Items.Add(itm);
                lstBundles.Enabled = false;
            } else {
                lstBundles.Enabled = true;
            }
            reader.Close();
        }
        db.CloseConnection();
    }

    /// <summary>
    /// Checks an output format has been selected
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.ServerValidateEventArgs"/> instance containing the event data.</param>
    protected void vldFormatRequired_ServerValidate(object sender, ServerValidateEventArgs e) {
        e.IsValid = radFormat.SelectedValue != null && radFormat.SelectedValue.Length > 0;
    }
}
